package parser;

import java.util.ArrayList;
import java.util.List;


public class Node {
	protected boolean isOutput;
	protected boolean isInPath;
	protected boolean isAttribute;
	protected String constraint;
	protected String type;
	protected Node parent;
	protected Node ancestor;
	protected List<Node> child;
	protected List<Node> descendant;
	protected List<Node> simList;
	protected List<Node> cPar;
	protected List<Node> auganc;


	public Node(String newType) {
		isOutput = false;
		isInPath = false;
		isAttribute = false;
		constraint = null;
		type = newType;
		parent = null;
		child = new ArrayList<Node>();
		ancestor = null;
		descendant = new ArrayList<Node>();
		simList = new ArrayList<Node>();
		cPar = new ArrayList<Node>();
		auganc = new ArrayList<Node>();
	}

	public Node(String newType, String newConstraint) {
		this(newType);
		isAttribute = true;
		constraint = newConstraint;
	}	

	public boolean isInPath() {
		return isInPath;
	}

	public void setInPath(boolean isInPath) {
		this.isInPath = isInPath;
	}

	public boolean isAttribute() {
		return isAttribute;
	}

	public void setAttribute(boolean isAttribute) {
		if (!isAttribute)
			this.constraint = null;

		this.isAttribute = isAttribute;
	}

	public String getConstraint() {
		return constraint;
	}

	public void setConstraint(String constraint) {
		this.constraint = constraint;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public Node getParent() {
		return parent;
	}

	public void setParent(Node parent) {
		this.parent = parent;
		parent.updateChild(this, false);
	}

	public List<Node> getChild() {
		return child;
	}

	public void setChild(List<Node> child) {
		this.child = child;
		for (Node node : child)
			node.updateParent(this, false);
	}

	public Node getAncestor() {
		return ancestor;
	}

	public void setAncestor(Node ancestor) {
		this.ancestor = ancestor;
		ancestor.updateDecendant(this, false);
	}

	public List<Node> getDecendant() {
		return descendant;
	}

	public void setDecendant(List<Node> descendant) {
		this.descendant = descendant;
		for (Node node : descendant)
			node.updateAncestor(this, false);
	}

	private void updateAncestor(Node newAncestor, boolean update) {
		ancestor = newAncestor;
		if (update) {
			newAncestor.updateDecendant(this, false);
		}
	}

	private void updateDecendant(Node newDecendant, boolean update) {
		descendant.add(newDecendant);
		if (update) {
			newDecendant.updateAncestor(this, false);
		}
	}

	private void updateParent(Node newParent, boolean update) {
		parent = newParent;
		if (update)
			newParent.updateChild(this, false);
	}

	private void updateChild(Node newChild, boolean update) {
		child.add(newChild);
		if (update) {
			newChild.updateParent(this, false);
		}
	}

	public void addAncestor(Node newAncestor) {
		updateAncestor(newAncestor, true);
	}

	public void addDecendant(Node newDecendant) {
		updateDecendant(newDecendant, true);
	}

	public void addParent(Node newParent) {
		updateParent(newParent, true);
	}

	public void addChild(Node newChild) {
		updateChild(newChild, true);
	}

	public void removeChild(Node rChild) {
		child.remove(rChild);
	}

	public void removeDecendant(Node rDecendant) {
		descendant.remove(rDecendant);
	}

	public void setOutput(boolean isOutput) {
		this.isOutput = isOutput;
	}
	
	public boolean isOutput() {
		return isOutput;
	}

	public boolean isLeaf() {
		return child.isEmpty() && descendant.isEmpty();
	}

	public void setCPar(List<Node> cPar) {
		this.cPar = cPar;
	}

	public List<Node> getCPar() {
		return cPar;
	}

	public void setAuganc(List<Node> auganc) {
		this.auganc = auganc;
	}

	public List<Node> getAuganc() {
		return auganc;
	}

	public void addSim(Node newNode) {
		simList.add(newNode);
	}

	public List<Node> getSimList() {
		return simList;
	}

	// end of newly added
	// get all the ancestors
	public List<Node> getAncestorList(List<Node> ancestorList, Node node) {
		Node ancestor = node.getAncestor();
		Node parent = node.getParent();
		if (ancestor != null) {
			ancestorList.add(ancestor);
			getAncestorList(ancestorList, ancestor);
		}
		if (parent != null) {
			ancestorList.add(parent);
			getAncestorList(ancestorList, parent);
		}
		return ancestorList;
	}
}